using System;
using System.Runtime.CompilerServices;
using System.Threading;

namespace Triton.Game
{
	public abstract class PerCachedValue<T>
	{
		private readonly Func<T> func_0;

		private bool bool_0;

		private T gparam_0;

		[CompilerGenerated]
		private EventHandler<CacheUpdateEvent> eventHandler_0;

		public T Value
		{
			get
			{
					if (!TritonHs.Memory.Executor.IsInsideHook)
					{
						//Triton.Common.LogUtilities.Logger.GetLoggerInstanceForType().ErrorFormat("------------------------------------------------------");
						throw new InvalidOperationException("!IsInsideHook");
					}
				if (ShouldUpdateCache(bool_0))
				{
					bool_0 = false;
					gparam_0 = func_0();
					if (eventHandler_0 != null)
					{
						Delegate[] invocationList = eventHandler_0.GetInvocationList();
						for (int i = 0; i < invocationList.Length; i++)
						{
							invocationList[i].DynamicInvoke(null, new CacheUpdateEvent());
						}
					}
				}
				return gparam_0;
			}
		}

		public event EventHandler<CacheUpdateEvent> OnCacheUpdate
		{
			[CompilerGenerated]
			add
			{
				EventHandler<CacheUpdateEvent> eventHandler = eventHandler_0;
				EventHandler<CacheUpdateEvent> eventHandler2;
				do
				{
					eventHandler2 = eventHandler;
					EventHandler<CacheUpdateEvent> value2 = (EventHandler<CacheUpdateEvent>)Delegate.Combine(eventHandler2, value);
					eventHandler = Interlocked.CompareExchange(ref eventHandler_0, value2, eventHandler2);
				}
				while ((object)eventHandler != eventHandler2);
			}
			[CompilerGenerated]
			remove
			{
				EventHandler<CacheUpdateEvent> eventHandler = eventHandler_0;
				EventHandler<CacheUpdateEvent> eventHandler2;
				do
				{
					eventHandler2 = eventHandler;
					EventHandler<CacheUpdateEvent> value2 = (EventHandler<CacheUpdateEvent>)Delegate.Remove(eventHandler2, value);
					eventHandler = Interlocked.CompareExchange(ref eventHandler_0, value2, eventHandler2);
				}
				while ((object)eventHandler != eventHandler2);
			}
		}

		protected PerCachedValue(Func<T> producer)
		{
			if (producer == null)
			{
				throw new ArgumentNullException("producer");
			}
			func_0 = producer;
		}

		protected abstract bool ShouldUpdateCache(bool force);

		public static implicit operator T(PerCachedValue<T> pfcv)
		{
			return pfcv.Value;
		}

		public void RequestCacheFlush()
		{
			bool_0 = true;
		}
	}
}
